<?php

/**
 * The Doctrine resource.
 *
 * @package App
 * @subpackage Resource
 */    
class App_Resource_Doctrine extends Zend_Application_Resource_ResourceAbstract {
	
	/**
     * Configuration options for Doctrine.
     *
     * @var \Doctrine\ORM\Configuration
     */
    protected $_config;
	
	/**
	 * (non-PHPdoc)
	 * @see Zend_Application_Resource_Resource::init()
	 * @return Doctrine\ORM\EntityManager
	 */
	public function init() {
		$options = $this->getOptions();
        $this->_config = new \Doctrine\ORM\Configuration();

        $this->_initClassLoader();
        
        // Metadata driver
        $this->_initMetadataDriver();
        
        // Set up caches
        $this->_initCache();

        // Proxy configuration
        $this->_initProxy();

        // Database connection information
        $connectionOptions = $this->_initConnection();
        
        // Create EntityManager
        $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $this->_config);
        Zend_Registry::set('em', $em);
        return $em;
	}

	/**
     * 
     * @return void
     */
    protected function _initClassLoader()
    {
    	$options = $this->getOptions();
        // Proxies
        // The namespace of the classes to load.
    	// $includePath The base include path to use.
        $classLoader = new \Doctrine\Common\ClassLoader(
        	$options['proxy']['namespace'],
        	$options['proxy']['directory']
        );
        $classLoader -> register();
        // Repositories
        $directories = $options['repository']['directories'];
        foreach ($directories as $directory) {
        	$classLoader = new \Doctrine\Common\ClassLoader(
        			$options['repository']['namespace'],
        			$directory
        	);
        	$classLoader -> register();
        }
        
        // Entities
        // The namespace of the classes to load.
        // $includePath The base include path to use.
        $entityPaths = $options['metadata']['entityPaths'];
        foreach ($entityPaths as $entityPath) {
        	$classLoader = new \Doctrine\Common\ClassLoader(
        			$options['metadata']['entitiesPathNamespace'],
        			$entityPath
        	);
        	$classLoader -> register();
        }
    }
	
	/**
     * Initialize metadata driver from resource options.
     *
     * @return void
     */
    protected function _initMetadataDriver()
    {
        $options = $this->getOptions();
        $mappingPaths = $options['metadata']['mappingPaths'];
        $driver = $this->_config->newDefaultAnnotationDriver($mappingPaths);        
        $this->_config->setMetadataDriverImpl($driver);        
    }
    
    /**
     * Initialize Doctrine cache configuration from resource options.
     *
     * @return void
     */
    protected function _initCache()
    {
        $options = $this->getOptions();
        switch($options['cache']) {
            case 'apc':
                $cache = new \Doctrine\Common\Cache\ApcCache();
                break;

            case 'memcache':
                $cache = new \Doctrine\Common\Cache\MemcacheCache();
                break;

            case 'xcache':
                $cache = new \Doctrine\Common\Cache\XcacheCache();
                break;

            default:
                $cache = new \Doctrine\Common\Cache\ArrayCache();
        }
        $this->_config->setMetadataCacheImpl($cache);
        $this->_config->setQueryCacheImpl($cache);
    }
    
	/**
     * Initialize Doctrine proxy configuration from resource options.
     *
     * @return void
     */
    protected function _initProxy()
    {
        $options = $this->getOptions();
        $this->_config->setProxyDir(isset($options['proxy']['directory']) ? $options['proxy']['directory'] : APPLICATION_PATH . '/model/proxies');
        $this->_config->setProxyNamespace(isset($options['proxy']['namespace']) ? $options['proxy']['namespace'] : 'model\proxies');
    }
    
	/**
     * Initialize Doctrine connection configuration from resource options.
     *
     * @return void
     */
    protected function _initConnection()
    {
        $options = $this->getOptions();
        return $options['connection'];
    }
}